#include "simulate.h"

int tsw1,tsw2;
float err1;

Simulate::~Simulate(void){
	passiveGates.clear();	
}

void Simulate::initSimulateHybrid(){

#ifdef DEBUG_SIMULATE        
        
          for(int i=0; i<Ci->signalSize(); ++i)
          {
                  if(Ci->getSignal(i)->inputSize())
                          cout <<"Signal name " << Ci->getSignal(i)->getName() << " is Traced? "<<
                                  Ci->getSignal(i)->getTraced() << " Input Name " << Ci->getSignal(i)->getInput(0)->getName() << endl;
                  if(Ci->getSignal(i)->outputSize())
                          cout <<"Signal name " << Ci->getSignal(i)->getName() << " is Traced? "<<
                                  Ci->getSignal(i)->getTraced() << " Outputput Name " << Ci->getSignal(i)->getOutput(0)->getName() << endl;
          }
        
#endif 
        
	for(int i=0; i<Ci->signalSize(); ++i){
                if(Ci->getSignal(i)->getTraced() == false) 
                {
                        Ci->getSignal(i)->setVal(Z);
                        Ci->getSignal(i)->setFlag0(0);
                        Ci->getSignal(i)->setFlag1(0);
                }
                Ci->getSignal(i)->stored = 0;
        }

}

void Simulate::initSimulate(bool a){
	for(int i=0; i<Ci->signalSize(); ++i){
		Ci->getSignal(i)->setVal(Z);
		//Ci->getSignal(i)->val = Z;
		Ci->getSignal(i)->setFlag0(0);
		Ci->getSignal(i)->setFlag1(0);
	}
	for(int i=0; i<Ci->flipflopSize(); ++i)
		Ci->getFlipflop(i)->getOutput(0)->setVal(Zero);
}

void Simulate::initSimulate(void){
	for(int i=0; i<Ci->signalSize(); ++i){
		Ci->getSignal(i)->setVal(Z);
		Ci->getSignal(i)->val = Z;
		Ci->getSignal(i)->sw = 0;
		Ci->getSignal(i)->sw1 = 0;
		Ci->getSignal(i)->setFlag0(0);
		Ci->getSignal(i)->setFlag1(0);
	}
	for(int i=0; i<Ci->flipflopSize(); ++i)
		Ci->getFlipflop(i)->getOutput(0)->setVal(Zero);
}

void Simulate::initSimulateGolden(void){
	for(int i=0; i<Ci->signalSize(); ++i){
		if(!Ci->getSignal(i)->getTraced()){
			Ci->getSignal(i)->setVal(Z);
			Ci->getSignal(i)->setFlag0(0);
			Ci->getSignal(i)->setFlag1(0);
		}
	}
}

void Simulate::setResets(void){
	for(int i=0; i<Ci->flipflopSize(); ++i)
		Ci->getFlipflop(i)->getInput(2)->setVal(One);
	
	for(int i=0; i<Ci->signalSize(); ++i)
		if(Ci->getSignal(i)->getName()[0]=='R')
			Ci->getSignal(i)->setVal(One);
	return;
}

void Simulate::setSigValues(vector<Signal *> sigs, vector<Value> vals){
	for(unsigned i=0; i<sigs.size(); ++i)
		sigs[i]->setVal(vals[i]);
}

void Simulate::setTraceValues(vector<Value> vals){
	for(unsigned i=0; i<tracedSigs.size(); ++i)
		tracedSigs[i]->setVal(vals[i]);
}

void Simulate::initGates(void){
	for(int i=0; i<Ci->gateSize(); ++i){
		Ci->getGate(i)->setVisited(false);
		Ci->getGate(i)->setBackwardVisited(false);
		Ci->getGate(i)->passive = false;
	}
	for(int i=0; i<Ci->flipflopSize(); ++i){
		Ci->getFlipflop(i)->setVisited(false);
		Ci->getFlipflop(i)->setBackwardVisited(false);
	}
	return;
}

bool Simulate::sim1cycleExh(void){
	bool check = true;
	bool cont=false;
	while(check){
		check = false;
/*		for(int i=0; i<Ci->inputSize(); ++i){
                if(!Ci->getInput(i)->getVisited())
                if(Ci->getInput(i)->isActive()){
                check = true;
                cont=true;
                }
                }*/
		for(int i=0; i<Ci->gateSize(); ++i){
			if(!Ci->getGate(i)->getVisited())
				if(Ci->getGate(i)->isActive()){
					check = true;
					cont=true;
				}
                }
        }
        return cont;
}				

bool Simulate::simHybrid(void)
{
        list<Signal*> sigList;
	bool cont=false;
        
        for(int i=0; i<Ci->flipflopSize(); ++i)
                if(Ci->getFlipflop(i)->getOutput(0)->getTraced())
                {
                        Ci->getFlipflop(i)->setInput();
                        sigList.push_back(Ci->getFlipflop(i)->getInput(1));
			sigList.push_back(Ci->getFlipflop(i)->getOutput(0));
                }
        
        Signal *s;
	while (!sigList.empty())
        {
                s = sigList.front();
                sigList.erase(sigList.begin());
                
                if(s->stored == 1)
                        continue;
#ifdef DEBUG_SIMULATE
                cout<<"Current signals in list are"<<endl;
                for(list<Signal*>::iterator it=sigList.begin(); it!=sigList.end(); ++it)
                        cout<<(*it)->getName()<<"\t";
                cout<<endl;
                
                cout<<"signal under simulation "<< s->getName() << " value " << s->getVal()<< endl;
                cin.get();
#endif                
                s->stored = 1;
                
                if(s->outputSize()!=0){
                        if(s->getOutput(0)->signature()!=INPUT){
                                for(int i=0; i<s->outputSize(); ++i){
                                        
                                        if(s->getOutput(i)->isActive()){
                                                cont=true;
                                                
                                                for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b') 
                                                                sigList.push_back(s->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                        else{
                                
                                for(int i=1; i<s->outputSize(); ++i){
                                        
                                        if(s->getOutput(i)->isActive()){
                                                
                                                cont=true;	
                                                for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' )
                                                                sigList.push_back(s->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                }
                if(s->inputSize()!=0){
                        if(s->getInput(0)->signature()!=OUTPUT){
                                for(int i=0; i<s->inputSize(); ++i){
                                        
                                        if(s->getInput(i)->isBackwardActive()){
                                                
                                                s->getInput(i)->setBackwardVisited(true);
                                                cont=true;
                                                
                                                for(int j=0; j<s->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && s->getInput(i)->getInput(j)->getName().c_str()[0] != 'b')
                                                                sigList.push_back(s->getInput(i)->getInput(j));
                                                }
                                        }
                                }
                        }
                        else
                        {
                                for(int i = 1; i < s->inputSize(); ++i){
                                        
                                        if(s->getInput(i)->isBackwardActive()){
                                                
                                                s->getInput(i)->setBackwardVisited(true);
                                                cont=true;
                                                        
                                                for(int j=0; j<s->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && s->getInput(i)->getInput(j)->getName().c_str()[0] != 'b') 
                                                           sigList.push_back(s->getInput(i)->getInput(j));
                                                }
                                        }
                                }
                        }
                }
        }
        
        return cont;
}


bool Simulate::sim1cycle(void){
	list<Signal*> sigList;
	bool cont=false;
	for(int i=0; i<Ci->flipflopSize(); ++i)
		if(Ci->getFlipflop(i)->getOutput(0)->isKnown())
			sigList.push_back(Ci->getFlipflop(i)->getOutput(0));
	for(int i=0; i<Ci->inputSize(); ++i)
		if(Ci->getInput(i)->getInput(0)->isKnown())
			sigList.push_back(Ci->getInput(i)->getInput(0));
	Signal *s;
        while (!sigList.empty())
        {
                s = sigList.front();
                sigList.erase(sigList.begin());
                if(s->outputSize()!=0){
                        if(s->getOutput(0)->signature()!=INPUT){
                                for(int i=0; i<s->outputSize(); ++i){
                                        if(s->getOutput(i)->signature()==FLIPFLOP)
                                                continue;
                                        if(s->getOutput(i)->isActive()){
                                                cont=true;	
                                                for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed)
                                                                sigList.push_back(s->getOutput(i)->getOutput(j));
                                                }
                                        }
				}
			}
			else{
				for(int i=1; i<s->outputSize(); ++i){
                                        if(s->getOutput(i)->signature()==FLIPFLOP)
                                                continue;
                                        if(s->getOutput(i)->isActive()){
                                                cont=true;	
                                                for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed)
                                                                sigList.push_back(s->getOutput(i)->getOutput(j));
                                                }
                                        }
				}
			}
		}
	}
        return cont;
}				
	
bool Simulate::sim1cycleBackward(void){
	list<Signal*> sigList;
	bool cont=false;
	for(int i=0; i<Ci->flipflopSize(); ++i)
		if(Ci->getFlipflop(i)->getInput(1)->isKnown())
			sigList.push_back(Ci->getFlipflop(i)->getInput(1));
	Signal *s;
        while (!sigList.empty())
        {
                s = sigList.back();
                sigList.pop_back();
                //cout<<s->getName()<<endl;
                if(s->inputSize()!=0){
                        if(s->getInput(0)->signature()!=OUTPUT){
                                for(int i=0; i<s->inputSize(); ++i){
                                        if(s->getInput(i)->signature()==FLIPFLOP){
                                                continue;
                                        }
					if(s->getInput(i)->isBackwardActive()){
						s->getInput(i)->setBackwardVisited(true);
						cont=true;
						
                                                for(int j=0; j<s->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed)
                                                                sigList.push_back(s->getInput(i)->getInput(j));
                                                }
					}
				}
			}
			else
				for(int i=1; i<s->inputSize(); ++i){
					if(s->getInput(i)->signature()==FLIPFLOP){
                                                continue;
                                        }
					if(s->getInput(i)->isBackwardActive()){
						s->getInput(i)->setBackwardVisited(true);
						cont=true;
						
                                                for(int j=0; j<s->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed)
                                                                sigList.push_back(s->getInput(i)->getInput(j));
                                                }
					}
				}
                }
	}

        return cont;
}				
	
void Simulate::dump(void){
        for(int i=0; i<Ci->signalSize(); ++i)
                cout<<Ci->getSignal(i)->getName()<<" : "<<Ci->getSignal(i)->getVal()<<','<<Ci->getSignal(i)->getP0()<<','<<Ci->getSignal(i)->getP1()<<endl;
}

void Simulate::dumpOutput(void){
        for(int i=0; i<Ci->outputSize(); ++i)
                cout<<Ci->getOutput(i)->getOutput(0)->getName()<<" : "<<Ci->getOutput(i)->getOutput(0)->getVal()<<endl;
}

void Simulate::simNcycle(int n){
	sim1cycle();
	cin.get();
	for(int i=1; i<n; ++i){
		for(int j=0; j<Ci->flipflopSize(); ++j){
			
			Ci->getFlipflop(j)->setOutput();

		}
		sim1cycle();
	}
}

bool Simulate::sim_event_cycle1(void){
	
        bool test = true;
        bool test2 = false;
        while(test){
                test = false;
                for(int i=0; i<passive.size(); ++i){				
                        if(passive[i]->isActive()){
                                test2 = true;
                                passive.erase(passive.begin()+i);
                                --i;
                                test = true;
                        }
                }
        }
        return test2;
}

bool Simulate::sim_event_back_cycle1(void){
	
        bool test = true;
        bool test2 = false;
        while(test){
                test = false;
                for(int i=0; i<passive.size(); ++i){				
                        if(passive[i]->isBackwardActive()){
                                test2 = true;
                                passive.erase(passive.begin()+i);
                                --i;
                                test = true;
                        }
                }
        }
        return test2;
}

void Simulate::sim_event_cycle(void){
	
        bool test = true;
        while(test){
                test = false;
                for(int i=0; i<passive.size(); ++i){
                        if(passive[i]->isActive()){
                                for(int k=0; k<passive[i]->outputSize(); ++k)
                                        for(int k1=0; k1<passive[i]->getOutput(k)->outputSize(); ++k1)
						if(!(passive[i]->getOutput(k)->getOutput(k1)->passive)){
							passive[i]->getOutput(k)->getOutput(k1)->passive = true;
							passive.push_back(passive[i]->getOutput(k)->getOutput(k1));
						}
                                passive[i]->passive = false;
                                passive.erase(passive.begin()+i);
                                --i;
                                test = true;
                        }
                }
        }
}

void Simulate::sim_event(bool fwBw){
	
	passive.clear();
	for(int i=0; i<Ci->gateSize(); ++i)
		passive.push_back(Ci->getGate(i));
	bool test = true;
	while(test){
		if(fwBw){
			test = sim_event_cycle1();
			for(int i=0; i<Ci->flipflopSize(); ++i){
				Ci->getFlipflop(i)->setOutput();
			}
		}
		else{
			test = sim_event_back_cycle1();
			for(int i=0; i<Ci->flipflopSize(); ++i){
				Ci->getFlipflop(i)->setInput();
			}
		}
	}
}


bool Simulate::simAllCycle(){

	bool test = false;
	sim1cycle();
	for(int j=0; j<Ci->flipflopSize(); ++j){
		Ci->getFlipflop(j)->setOutput();
	}
	sim1cycle();sim_event(true);
	return test;
}

void Simulate::simNcycleBackward(int n){
	sim1cycleBackward();
	cin.get();
	for(int i=1; i<n; ++i){
		for(int j=0; j<Ci->flipflopSize(); ++j){
			
			Ci->getFlipflop(j)->setInput();
                        
		}
		sim1cycleBackward();
		cin.get();
	}
}

bool Simulate::simAllCycleBackward(){
	for(int j=0; j<Ci->flipflopSize(); ++j){			
                Ci->getFlipflop(j)->setInput();
        }		
	sim1cycleBackward();
	return true;
}

extern vector<int> sim_vals;
#ifdef NEW
void Simulate::forwardSim_event(int n){
	
        Value vals[]={Zero,One,Z,X};
        list<Signal*> sigList;
	vector<Signal*> sig;
	vector<Value> val;
        int count= 0;
        
	for(int i=0; i<Ci->inputSize(); ++i){
		sig.push_back(Ci->getInput(i)->getInput(0));
	}
        
        for(int j=0; j<Ci->flipflopSize(); ++j){
                if(Ci->getFlipflop(j)->getOutput(0)->isKnown() == false)
                        Ci->getFlipflop(j)->getOutput(0)->setVal(Zero);
        }
        
        //cout<<"After first cycle of simulation......."<<endl;
        //for(int i=0; i<Ci->signalSize(); ++i)
        //cout<<"signal name is "<<Ci->getSignal(i)->getName()<<" value is "<<Ci->getSignal(i)->getVal()<<endl;
        
        for(int i=0; i<Ci->signalSize(); ++i){
                Ci->getSignal(i)->stored = 0;
                Ci->getSignal(i)->setFlag0(0);
                Ci->getSignal(i)->setFlag1(0);
        }
        
        //before go into the loop, let's first deal with the situation when
        //after simulate 1 cycle, there are still unknow signals
        for(int cnt=0; cnt<n; ++cnt){
                
                for(int i=0; i<Ci->signalSize(); ++i)
                        Ci->getSignal(i)->stored = 0;
                
		val.clear();
		for(int i=0; i<Ci->inputSize(); ++i){
			if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b'){
				val.push_back(vals[rand()%2]);
				for(int k=0; k<Ci->getInput(i)->getInput(0)->outputSize(); ++k){
					if(!(Ci->getInput(i)->getInput(0)->getOutput(k)->passive)){
						Ci->getInput(i)->getInput(0)->getOutput(k)->passive = true;
						passive.push_back(Ci->getInput(i)->getInput(0)->getOutput(k));
					}
				}
			}
			else{
				val.push_back(Zero);
			}
		}		
		
		setSigValues(sig,val);
                bool cont=false;
                
                //this part is for input
                for(int i = 0; i < sig.size(); i++)
                {
                        if( sim_vals[sig[i]->getIndex()] != val[i] && sig[i]->getName()[0] != 'b' && sig[i]->getName()[0] != 'n')
                        {
                                sim_vals[sig[i]->getIndex()] = val[i];
                                sigList.push_back(sig[i]);
                        }
                }
                
                //cout<<"signals in the list"<<endl;
                //for(list<Signal*>::iterator it=sigList.begin(); it!=sigList.end(); ++it)
                //cout<<(*it)->getName()<<"\t";
                //cout<<endl;
                
                Signal *s;
                while (!sigList.empty())
                {
                        s = sigList.front();
                        sigList.erase(sigList.begin());
                        
                        //this is the real problem, add these lines are
                        //wrong, let's suppose the same node can be
                        //accessed at most twice, should be the case
                        if(s->stored == 2)
                                continue;
#ifdef DEBUG_SIMULATE
                        cout<<"Current signals in list are"<<endl;
                        for(list<Signal*>::iterator it=sigList.begin(); it!=sigList.end(); ++it)
                                cout<<(*it)->getName()<<"\t";
                        cout<<endl;
                
                        cout<<"signal under simulation "<< s->getName() << " value " << s->getVal()<< endl;
                        cin.get();
#endif                
                        s->stored++;
                        if(s->outputSize()!=0){
                                if(s->getOutput(0)->signature()!=INPUT){
                                        for(int i=0; i<s->outputSize(); ++i){
                                                
                                                if(s->getOutput(i)->isActive()){
                                                        cont=true;
                                                        
                                                        for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                                
                                                                bool listed = false;
                                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                        if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                                listed = true;
                                                                }
                                                                if(s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' )
                                                                        sigList.push_back(s->getOutput(i)->getOutput(j));
                                                        }
                                                }
                                        }
                                }
                                else{
                                
                                        for(int i=1; i<s->outputSize(); ++i){
						
                                                if(s->getOutput(i)->isActive()){
                                                
                                                        cont=true;	
                                                        for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                                
                                                                bool listed = false;
                                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                        if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                                listed = true;
                                                                }
                                                                
                                                                if(s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' )
                                                                        sigList.push_back(s->getOutput(i)->getOutput(j));
                                                        }
                                                }
                                        }
                                }
                        }
                }

                for(int si=0; si<Ci->signalSize(); ++si){
                        
                        if(Ci->getSignal(si)->getVal()==Zero)
                                Ci->getSignal(si)->setFlag0(Ci->getSignal(si)->getFlag0()+1);
                        else if(Ci->getSignal(si)->getVal()==One)
                                Ci->getSignal(si)->setFlag1(Ci->getSignal(si)->getFlag1()+1);
                        else
                        {
                                count++;
                        }
                }
        
                //collecting information for hybrid gates
                int k,bit;
                for(int i = 0; i < Ci->hgateSize(); ++i){
                
                        //collecting backtracing events
                        for(int j = 0; j < Ci->getHGate(i)->inputSize(); j++)
                        {
                                bit = 0;
                                for(k = 0; k < Ci->getHGate(i)->inputSize(); k++)
                                {
                                        if(k == j)
                                                continue;
                                        else
                                                if(((HybridNode*)Ci->getHGate(i))->events[2*j+0][bit] != Ci->getSignal(Ci->getHGate(i)->getInput(k)->getIndex())->getVal()
                                                   && ((HybridNode*)Ci->getHGate(i))->events[2*j+0][bit] != 2)
                                                        break;
                                                else
                                                        bit++;
                                }                        
                
                                if(k == Ci->getHGate(i)->inputSize())
                                {
                                        for(k = 0; k < Ci->getHGate(i)->outputSize(); k++)
                                                if(((HybridNode*)Ci->getHGate(i))->events[2*j+0][Ci->getHGate(i)->inputSize()-1+k] 
                                                   != Ci->getSignal(Ci->getHGate(i)->getOutput(k)->getIndex())->getVal() && 
                                                   ((HybridNode*)Ci->getHGate(i))->events[2*j+0][Ci->getHGate(i)->inputSize()-1+k] != 2)
                                                        break;
                                }
                                else
                                        continue;
                        
                                if(k == Ci->getHGate(i)->outputSize())
                                {
                                        ((HybridNode*)Ci->getHGate(i))->BR_event[2*j+0]++;
                                        continue;
                                }
                        }
                
                        for(int j = 0; j < Ci->getHGate(i)->inputSize(); j++)
                        {
                                bit = 0;
                                for(k = 0; k < Ci->getHGate(i)->inputSize(); k++)
                                {
                                        if(k == j)
                                                continue;
                                        else
                                                if(((HybridNode*)Ci->getHGate(i))->events[2*j+1][bit] != Ci->getSignal(Ci->getHGate(i)->getInput(k)->getIndex())->getVal()
                                                   && ((HybridNode*)Ci->getHGate(i))->events[2*j+1][bit] != 2)
                                                        break;
                                                else
                                                        bit++;
                                }
                        
                                if(k == Ci->getHGate(i)->inputSize())
                                {
                                        for(k = 0; k < Ci->getHGate(i)->outputSize(); k++)
                                                if(((HybridNode*)Ci->getHGate(i))->events[2*j+1][Ci->getHGate(i)->inputSize()-1+k] 
                                                   != Ci->getSignal(Ci->getHGate(i)->getOutput(k)->getIndex())->getVal()
                                                   && ((HybridNode*)Ci->getHGate(i))->events[2*j+1][Ci->getHGate(i)->inputSize()-1+k] != 2)
                                                        break;
                                }
                                else
                                        continue;
                        
                                if(k == Ci->getHGate(i)->outputSize())
                                {
                                        ((HybridNode*)Ci->getHGate(i))->BR_event[2*j+1]++;
                                        continue;
                                }
                        }

                        //collecting forward resotre information
                        int cnt,flag;
                        vector<int*>::iterator it;
                        for(int j = 0; j < Ci->getHGate(i)->outputSize(); j++)
                        {
                                flag = 0;
                                cnt = 0;
                                for(it = ((HybridNode*)Ci->getHGate(i))->OFR0.begin(); it != ((HybridNode*)Ci->getHGate(i))->OFR0.end(); it++)
                                {
                                        for(k = 0; k < Ci->getHGate(i)->inputSize(); k++)
                                                if((*it)[k] != Ci->getSignal(Ci->getHGate(i)->getInput(k)->getIndex())->getVal() 
                                                   && (*it)[k] != 2)
                                                        break;
                                
                                        if(k == Ci->getHGate(i)->inputSize())
                                        {
                                                flag = 1;
                                                break;
                                        }
                                        cnt++;
                                }
                        
                                if(flag == 1)
                                {
                                        ((HybridNode*)Ci->getHGate(i))->FR0_event[cnt]++;
                                        continue;
                                }
                        
                                flag = 0;
                                cnt = 0;
                                for(it = ((HybridNode*)Ci->getHGate(i))->OFR1.begin(); it != ((HybridNode*)Ci->getHGate(i))->OFR1.end(); it++)
                                {
                                        for(k = 0; k < Ci->getHGate(i)->inputSize(); k++)
                                                if((*it)[k] != Ci->getSignal(Ci->getHGate(i)->getInput(k)->getIndex())->getVal() 
                                                   && (*it)[k] != 2)
                                                        break;
                                
                                        if(k == Ci->getHGate(i)->inputSize())
                                        {
                                                flag = 1;
                                                break;
                                        }
                                        cnt++;
                                }
                        
                                if(flag == 1)
                                {
                                        ((HybridNode*)Ci->getHGate(i))->FR1_event[cnt]++;
                                        continue;
                                }
                        }
                        
                        cnt = 0;
                        //collecting extra events
                        for(it = ((HybridNode*)Ci->getHGate(i))->extra_events.begin(); it != ((HybridNode*)Ci->getHGate(i))->extra_events.end(); it++)
                        {
                                flag = 0;
                                for(k = 0; k < Ci->getHGate(i)->inputSize(); k++)
                                {
                                        if((*it)[0] == k)
                                                continue;
                                        else
                                        {
                                                if((*it)[k+2] != Ci->getSignal(Ci->getHGate(i)->getInput(k)->getIndex())->getVal() 
                                                   && (*it)[k+2] != 2)
                                                        break;
                                        }
                                }
                        
                                if(k != Ci->getHGate(i)->inputSize())
                                        continue;
                        
                                for(k = Ci->getHGate(i)->inputSize()-1; k < Ci->getHGate(i)->inputSize()-1+Ci->getHGate(i)->outputSize(); k++)
                                {
                                        if((*it)[k+2] != Ci->getSignal(Ci->getHGate(i)->getOutput(k-Ci->getHGate(i)->inputSize()+1)->getIndex())->getVal() 
                                           && (*it)[k+2] != 2)
                                                break;
                                }
                        
                                if(k != Ci->getHGate(i)->inputSize()-1+Ci->getHGate(i)->outputSize())
                                        continue;
                                else
                                        ((HybridNode*)Ci->getHGate(i))->Extra_br_event[cnt]++;
                                
                                cnt++;
                        }
                        
                }
        }
        
        cout<<"Number of Unknow signals after simulation is "<<count/MC_NUM<<endl;
        
        //this part is for writing the probability file
	for(int i=0; i<Ci->signalSize(); ++i){
        Ci->getSignal(i)->setP0( ((float)Ci->getSignal(i)->getFlag0()) / n);
                Ci->getSignal(i)->setP1( ((float)Ci->getSignal(i)->getFlag1()) / n);
	}
}
#else
void Simulate::forwardSim_event(int n){
	
        Value vals[]={Zero,One,Z,X};
	initSimulate();
	
	vector<Signal*> sig;
	vector<Value> val;
	
	for(int i=0; i<Ci->inputSize(); ++i){
		sig.push_back(Ci->getInput(i)->getInput(0));
	}
	
	for(int cnt=0; cnt<n; ++cnt){
		
		val.clear();
		
		for(int i=0; i<Ci->inputSize(); ++i){
			if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b'){
				val.push_back(vals[rand()%2]);
				for(int k=0; k<Ci->getInput(i)->getInput(0)->outputSize(); ++k){
					if(!(Ci->getInput(i)->getInput(0)->getOutput(k)->passive)){
						Ci->getInput(i)->getInput(0)->getOutput(k)->passive = true;
						passive.push_back(Ci->getInput(i)->getInput(0)->getOutput(k));
					}
				}
			}
			else{
				val.push_back(Zero);
			}
		}		
		
		setSigValues(sig,val);
		
		for(int i=0; i<Ci->gateSize(); ++i)
			passive.push_back(Ci->getGate(i));
                
		sim_event_cycle();
                
		for(int i=0; i<Ci->flipflopSize(); ++i){
			Ci->getFlipflop(i)->setOutput();
		}
			
                for(int si=0; si<Ci->signalSize(); ++si){
                        
                        if(Ci->getSignal(si)->getVal()==Zero)
                                Ci->getSignal(si)->setFlag0(Ci->getSignal(si)->getFlag0()+1);
                        if(Ci->getSignal(si)->getVal()==One)
                                Ci->getSignal(si)->setFlag1(Ci->getSignal(si)->getFlag1()+1);
                }
	}
        
	for(int i=0; i<Ci->signalSize(); ++i){
	
                Ci->getSignal(i)->setP0( ((float)Ci->getSignal(i)->getFlag0()) / n);
                Ci->getSignal(i)->setP1( ((float)Ci->getSignal(i)->getFlag1()) / n);
			
                Ci->getSignal(i)->setFlag0(0);
                Ci->getSignal(i)->setFlag1(0);
	}
}
#endif

extern double criteria;
#ifdef NEW
void Simulate::forwardSimReg(int n){
	Value vals[]={Zero,One,Z,X};
	initSimulate();
        
        for(int gi=0; gi<Ci->gateSize(); ++gi){
                
                if(Ci->getGate(gi)->getName() == "NAND2") 
                        ((Nand2Node*)Ci->getGate(gi))->initEventStat();
                if(Ci->getGate(gi)->getName() == "NOR2")
                        ((Nor2Node*)Ci->getGate(gi))->initEventStat();
                
                Ci->getGate(gi)->correlated = 0;
                Ci->getGate(gi)->initCorStat();
        }
        
	vector<Signal*> sig;
	vector<Value> val;

	for(int i=0; i<Ci->inputSize(); ++i){
		if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b'){
			sig.push_back(Ci->getInput(i)->getInput(0));
			val.push_back(vals[rand()%2]);
		}
		else{
			sig.push_back(Ci->getInput(i)->getInput(0));
			val.push_back(One);
		}
	}	

	setSigValues(sig,val);

	sim1cycle();

	for(int i=0; i<Ci->flipflopSize(); ++i){
                Ci->getFlipflop(i)->setOutput();
        }
	
	for(int cnt=0; cnt<(n-1); ++cnt){
		sig.clear();
		val.clear();
                //if for this part we check the signals that have values
                //different from the previous cycle, we can use an
                //event-driven simulator for much faster simulation of
                //signal probabilities. 
		for(int i=0; i<Ci->inputSize(); ++i){
			if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b'){
				sig.push_back(Ci->getInput(i)->getInput(0));
				val.push_back(vals[rand()%2]);
			}
			else{
				sig.push_back(Ci->getInput(i)->getInput(0));
				val.push_back(Zero);
			}
		}
		setSigValues(sig,val);
		simAllCycle();	

		for(int si=0; si<Ci->signalSize(); ++si){
                        if(Ci->getSignal(si)->getVal()==Zero)
				Ci->getSignal(si)->setFlag0(Ci->getSignal(si)->getFlag0()+1);
			if(Ci->getSignal(si)->getVal()==One)
				Ci->getSignal(si)->setFlag1(Ci->getSignal(si)->getFlag1()+1);
		}
                
                int j,entry,ret_val;
                //go through all gates, no three-input gates
                for(int gi=0; gi<Ci->gateSize(); ++gi){
                        if(Ci->getGate(gi)->inputSize() == 2)//two inputs
                        {
                                entry=0;
                                for(j = 0; j < 2; j++)
                                {
                                        if(Ci->getGate(gi)->getInput(j)->getVal() == One)
                                                ret_val = 1;
                                        else if(Ci->getGate(gi)->getInput(j)->getVal() == Zero)
                                                ret_val = 0;
                                        else
                                                ret_val = -1;
                                        
                                        if(ret_val != -1)
                                                entry += ret_val * pow(2,j);
                                }
                                
                                if(Ci->getGate(gi)->getName() == "NAND2")
                                {
                                        if(Ci->getGate(gi)->getInput(0)->getVal() == One 
                                           && Ci->getGate(gi)->getInput(1)->getVal() == One)
                                                ((Nand2Node*)Ci->getGate(gi))->event_fr0_c++;
                                        else if(Ci->getGate(gi)->getOutput(0)->getVal() == One 
                                                && Ci->getGate(gi)->getInput(0)->getVal() == One)
                                                ((Nand2Node*)Ci->getGate(gi))->event_br0[0]++;
                                        else if(Ci->getGate(gi)->getOutput(0)->getVal() == One 
                                                && Ci->getGate(gi)->getInput(1)->getVal() == One)
                                                ((Nand2Node*)Ci->getGate(gi))->event_br0[1]++;
                                        else
                                        {
                                                
                                        }
                                }
                                
                                if(Ci->getGate(gi)->getName() == "NOR2")
                                {
                                        if(Ci->getGate(gi)->getInput(0)->getVal() == Zero 
                                           && Ci->getGate(gi)->getInput(1)->getVal() == Zero)
                                                ((Nor2Node*)Ci->getGate(gi))->event_fr1_c++;
                                        else if(Ci->getGate(gi)->getOutput(0)->getVal() == Zero 
                                                && Ci->getGate(gi)->getInput(0)->getVal() == Zero)
                                                ((Nor2Node*)Ci->getGate(gi))->event_br1[0]++;
                                        else if(Ci->getGate(gi)->getOutput(0)->getVal() == Zero 
                                                && Ci->getGate(gi)->getInput(1)->getVal() == Zero)
                                                ((Nor2Node*)Ci->getGate(gi))->event_br1[1]++;
                                        else
                                        {
                                                
                                        }
                                }

                                Ci->getGate(gi)->updateCorStat(entry);
                        }
                        else if(Ci->getGate(gi)->inputSize() == 3)//three inputs
                        {
                                entry=0;
                                for(j = 0; j < 3; j++)
                                {
                                        if(Ci->getGate(gi)->getInput(j)->getVal() == One)
                                                ret_val = 1;
                                        else if(Ci->getGate(gi)->getInput(j)->getVal() == Zero)
                                                ret_val = 0;
                                        else
                                                ret_val = -1;
                                        
                                        if(ret_val != -1)
                                                entry += ret_val * pow(2,j);
                                }
                                
                                Ci->getGate(gi)->updateCorStat(entry);
                        }
                        else
                        {
                                //do nothing
                        }
                }
                
	}//n cycles after
        
        /*
	for(int i=0; i<Ci->signalSize(); ++i){
                
		Ci->getSignal(i)->setP0( ((float)Ci->getSignal(i)->getFlag0()) / n);
		Ci->getSignal(i)->setP1( ((float)Ci->getSignal(i)->getFlag1()) / n);

		Ci->getSignal(i)->setFlag0(0);
		Ci->getSignal(i)->setFlag1(0);
	}
        */

        int c1=0,c2=0,c3=0;
        int cnt_two_in=0,cnt_three_in=0;
        int impossible=0;
        
        for(int gi=0; gi<Ci->gateSize(); ++gi){
#ifdef DEBUG_SIMULATE
                if(Ci->getGate(gi)->getName() == "NAND2")
                {
                        cout<<"Index is "<<Ci->getGate(gi)->index<<endl;
                        cout<<((Nand2Node*)Ci->getGate(gi))->event_fr0_c<<endl;
                        cout<<((Nand2Node*)Ci->getGate(gi))->event_br0[0]<<endl;
                        cout<<((Nand2Node*)Ci->getGate(gi))->event_br0[1]<<endl;
                }

                if(Ci->getGate(gi)->getName() == "NOR2")
                {
                        cout<<"Index is "<<Ci->getGate(gi)->index<<endl;
                        cout<<((Nor2Node*)Ci->getGate(gi))->event_fr1_c<<endl;
                        cout<<((Nor2Node*)Ci->getGate(gi))->event_br1[0]<<endl;
                        cout<<((Nor2Node*)Ci->getGate(gi))->event_br1[1]<<endl;
                }
#endif
                if(Ci->getGate(gi)->inputSize() == 2)//two inputs
                {
                        c2++;                          
                        
                        if((double)Ci->getGate(gi)->findMajority()/(double)n >= criteria)
                        {
                                cnt_two_in++;
                                Ci->getGate(gi)->correlated++;
                                if(Ci->getGate(gi)->getInput(0)->inputSize() > 1 
                                   || Ci->getGate(gi)->getInput(1)->inputSize() > 1)
                                        impossible++;
                        }
                }
                else if(Ci->getGate(gi)->inputSize() == 3)
                {
                        c3++;
                        
                        if((double)Ci->getGate(gi)->findMajority()/(double)n >= criteria/2)
                        {
                                cnt_three_in++;
                                Ci->getGate(gi)->correlated++;
                        }
                }
                else
                {
                        c1++;
                        //do nothing
                }
        }
        
        cout<<"total number of gates is "<<Ci->gateSize()<<endl;
        cout<<"# of one-input gates is "<<c1<<endl;
        cout<<"# of two-inputs gates is "<<c2<<endl;

        cout<<"# of three-inputs gates is "<<c3<<endl;
        cout<<"# of correlated two-inputs gates is "<<cnt_two_in<<endl;
        cout<<"# of impossible two-inputs gates is "<<impossible<<endl;
        cout<<"# of correlated three-inputs gates is "<<cnt_three_in<<endl;
        
	return;
}

#else
void Simulate::forwardSimReg(int n){
	Value vals[]={Zero,One,Z,X};
	initSimulate();
	
	vector<Signal*> sig;
	vector<Value> val;
	for(int i=0; i<Ci->inputSize(); ++i){
		if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b'){
			sig.push_back(Ci->getInput(i)->getInput(0));
			val.push_back(vals[rand()%2]);
		}
		else{
			sig.push_back(Ci->getInput(i)->getInput(0));
			val.push_back(One);
		}
	}	
	setSigValues(sig,val);
	sim1cycle();
	for(int i=0; i<Ci->flipflopSize(); ++i){
		Ci->getFlipflop(i)->setOutput();
	}
	for(int cnt=0; cnt<(n-1); ++cnt){
                sig.clear();
                val.clear();
                for(int i=0; i<Ci->inputSize(); ++i){
                        if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b'){
                                sig.push_back(Ci->getInput(i)->getInput(0));
                                val.push_back(vals[rand()%2]);
                        }
                        else{
                                sig.push_back(Ci->getInput(i)->getInput(0));
                                val.push_back(Zero);
                        }
                }
                setSigValues(sig,val);
                simAllCycle();	
                for(int gi=0; gi<Ci->gateSize(); ++gi){
                        if(Ci->getGate(gi)->signature()==NAND2)
                                if(Ci->getGate(gi)->getOutput(0)->getVal() != !(Ci->getGate(gi)->getInput(0)->getVal()&Ci->getGate(gi)->getInput(1)->getVal())){
                                        cout<<Ci->getGate(gi)->getName()<<endl;
                                        cout<<Ci->getGate(gi)->getOutput(0)->getName()<<endl;
                                        cout<<Ci->getGate(gi)->getOutput(0)->getVal()<<endl;
                                        cout<<Ci->getGate(gi)->getInput(0)->getVal()<<endl;
                                        cout<<Ci->getGate(gi)->getInput(1)->getVal()<<endl;
                                        cin.get();
                                }
                        if(Ci->getGate(gi)->signature()==NOR2)
                                if(Ci->getGate(gi)->getOutput(0)->getVal() != !(Ci->getGate(gi)->getInput(0)->getVal()|Ci->getGate(gi)->getInput(1)->getVal())){
                                        cout<<Ci->getGate(gi)->getName()<<endl;
                                        cout<<Ci->getGate(gi)->getOutput(0)->getName()<<endl;
                                        cout<<Ci->getGate(gi)->getOutput(0)->getVal()<<endl;
                                        cout<<Ci->getGate(gi)->getOutput(0)->getVal()<<endl;
                                        cin.get();
                                }
                        if(Ci->getGate(gi)->signature()==NOT)
                                if(Ci->getGate(gi)->getOutput(0)->getVal() != !(Ci->getGate(gi)->getInput(0)->getVal())){
                                        cout<<Ci->getGate(gi)->getName()<<endl;
                                        cout<<Ci->getGate(gi)->getInput(0)->getName()<<endl;
                                        cout<<Ci->getGate(gi)->getOutput(0)->getName()<<endl;
                                        cout<<Ci->getGate(gi)->getOutput(0)->getVal()<<endl;
                                        cout<<Ci->getGate(gi)->getInput(0)->getVal()<<endl;
                                        cin.get();
                                }
                }
			
                for(int si=0; si<Ci->signalSize(); ++si){
                        if(Ci->getSignal(si)->getVal()==Zero)
                                Ci->getSignal(si)->setFlag0(Ci->getSignal(si)->getFlag0()+1);
                        if(Ci->getSignal(si)->getVal()==One)
                                Ci->getSignal(si)->setFlag1(Ci->getSignal(si)->getFlag1()+1);
                }
	}
	for(int i=0; i<Ci->signalSize(); ++i){
	
                Ci->getSignal(i)->setP0( ((float)Ci->getSignal(i)->getFlag0()) / n);
                Ci->getSignal(i)->setP1( ((float)Ci->getSignal(i)->getFlag1()) / n);
			
                Ci->getSignal(i)->setFlag0(0);
                Ci->getSignal(i)->setFlag1(0);
	}
		
	return;
}
#endif

void Simulate::forwardGolden(int n)
{
        Value vals[]={Zero,One,Z,X};
	initSimulate();
	
	vector<Signal*> sig;
	vector<Value> val;
	for(int i=0; i<Ci->inputSize(); ++i){
		if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b'){
			sig.push_back(Ci->getInput(i)->getInput(0));
			val.push_back(vals[rand()%2]);
		}
		else{
			sig.push_back(Ci->getInput(i)->getInput(0));
			val.push_back(One);
		}
	}	
	setSigValues(sig,val);
	sim1cycle();
	for(int i=0; i<Ci->flipflopSize(); ++i){
		Ci->getFlipflop(i)->setOutput();
	}
	
	sig.clear();
        val.clear();
        for(int i=0; i<Ci->inputSize(); ++i){
                if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b'){
                        sig.push_back(Ci->getInput(i)->getInput(0));
                        val.push_back(vals[rand()%2]);
                }
                else{
                        sig.push_back(Ci->getInput(i)->getInput(0));
                        val.push_back(Zero);
                }
        }
        setSigValues(sig,val);
			
        //for(int i=0; i<Ci->inputSize(); ++i)
        //dumpFile<<Ci->getInput(i)->getIndex()<<" "<<Ci->getInput(i)->getInput(0)->getName()<<
        //" "<<Ci->getInput(i)->getInput(0)->getVal()<<endl;
        //dumpFile<<endl;
        
        //initSimulateGolden();
        
	bool test = true;
	while(test){
		test = false;
			
                simAllCycle();	
                for(int i=0; i<Ci->flipflopSize(); ++i)
                        if(!(Ci->getFlipflop(i)->getOutput(0)->isKnown())){
                                test=true;
                                break;
                        }

	}	
	return;
}
void Simulate::backwardSimReg(void){
	Value vals[]={Zero,One,Z,X};
	initSimulate();
	vector<Signal*> sig;
	vector<Value> val;
	for(int i=0; i<Ci->inputSize(); ++i){
                if(Ci->getInput(i)->getInput(0)->getName()[0] == 'b'){
                        sig.push_back(Ci->getInput(i)->getInput(0));
                        val.push_back(Zero);
                }
	}
		
	setSigValues(sig,val);
	sim1cycle();

	sig.clear();
	val.clear();
			
	for(int i=0; i<Ci->outputSize(); ++i){
		sig.push_back(Ci->getOutput(i)->getOutput(0));
		val.push_back(vals[rand()%2]);
	}
	
	setSigValues(sig,val);
	simAllCycleBackward();
	return;
}

void Simulate::simTraced(int cn){
        
	Value vals[]={Zero,One,Z,X};
	
	//initSimulate(true);
	vector<Signal*> sig;
	vector<Value> val;
	
	for(int i=0; i<Ci->inputSize(); ++i){
		sig.push_back(Ci->getInput(i)->getInput(0));
	}
	
        val.clear();
		
        for(int i=0; i<Ci->inputSize(); ++i){
                if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b'){
                        val.push_back(vals[rand()%2]);
                        for(int k=0; k<Ci->getInput(i)->getInput(0)->outputSize(); ++k){
                                if(!(Ci->getInput(i)->getInput(0)->getOutput(k)->passive)){
                                        Ci->getInput(i)->getInput(0)->getOutput(k)->passive = true;
                                        passive.push_back(Ci->getInput(i)->getInput(0)->getOutput(k));
                                }
                        }
                }
                else{
                        val.push_back(Zero);
                }
        }		
		
        setSigValues(sig,val);
	
	sim_event(true);
	
	for(int i=0; i<Ci->gateSize(); ++i){
		
                if((Ci->getGate(i)->getOutput(0)->val1 != Ci->getGate(i)->getOutput(0)->getVal())||(!(Ci->getSignal(i)->isKnown()))){
                        Ci->getGate(i)->getOutput(0)->sw1 +=1;
                        tsw1++;
                }
		
		Ci->getGate(i)->getOutput(0)->val1 = Ci->getGate(i)->getOutput(0)->getVal();
	}
	
	for(int i=0; i<Ci->flipflopSize(); ++i){
		
		//if((cn > 500)&& (cn<550))
                if((Ci->getFlipflop(i)->getOutput(0)->val1 != Ci->getFlipflop(i)->getOutput(0)->getVal())||(!(Ci->getSignal(i)->isKnown()))){
                        Ci->getFlipflop(i)->getOutput(0)->sw1 +=1;
                        tsw1++;
                }
		
		Ci->getFlipflop(i)->getOutput(0)->val1 = Ci->getFlipflop(i)->getOutput(0)->getVal();
	}
	
        //initSimulateGolden();
        //sim_event(true);
	//sim_event(false);
        
        initSimulateHybrid();
        simHybrid();
#ifdef DEBUG_SIMULATE
        cout<<"dumping all signals start......."<<endl;
        dump();
#endif
        
	return;
}

extern int MC_NUM;
double Simulate::computVN(){
	
        initSimulate();
        vector<Signal*> vn;
        long total_vn_cnt = 0;
        int n; long st;
	
	for(int k=0; k<MC_NUM; ++k){
		
                simTraced(k);
                //forwardGolden(k);
                vn.clear();
						
		for(int i=0; i<Ci->gateSize(); ++i){
			
                        if((Ci->getGate(i)->getOutput(0)->val != Ci->getGate(i)->getOutput(0)->getVal())||(!(Ci->getGate(i)->getOutput(0)->isKnown()))){
                                Ci->getGate(i)->getOutput(0)->sw +=1;
                                tsw2++;
                        }
			
			Ci->getGate(i)->getOutput(0)->val = Ci->getGate(i)->getOutput(0)->getVal();
		}
		
		for(int i=0; i<Ci->flipflopSize(); ++i){
			
                        if((Ci->getFlipflop(i)->getOutput(0)->val != Ci->getFlipflop(i)->getOutput(0)->getVal())||(!(Ci->getFlipflop(i)->getOutput(0)->isKnown()))){
                                Ci->getFlipflop(i)->getOutput(0)->sw +=1;
                                tsw2++;
                        }
			
			Ci->getFlipflop(i)->getOutput(0)->val = Ci->getFlipflop(i)->getOutput(0)->getVal();
		}
		
		err1 += (float(abs(tsw1-tsw2)))/max(tsw1,tsw2);
		for(int i=0; i<Ci->flipflopSize(); ++i){
			if(Ci->getFlipflop(i)->getOutput(0)->isKnown()){

				if(Ci->getFlipflop(i)->getOutput(0)->getVal())
					Ci->getFlipflop(i)->getOutput(0)->setFlag1(1);
				else
					Ci->getFlipflop(i)->getOutput(0)->setFlag0(1);
				bool test=true;
				for(unsigned j=0; j<vn.size(); ++j)
					if(vn[j]->getName()==Ci->getFlipflop(i)->getOutput(0)->getName()){
						test = false;
						break;
					}
				if(test)
					vn.push_back(Ci->getFlipflop(i)->getOutput(0));	
			}
		}
                
                total_vn_cnt += vn.size();
        }
        
	return (double)total_vn_cnt / (double)MC_NUM;
}

double Simulate::computVN(char* filename){
	
        initSimulate();
	//vector<Signal*> vn;
        vector<int> vn;
        long total_vn_cnt = 0;
        int n; long st;
        int traced_id;

	for(int k=0; k<MC_NUM; ++k){
		
                simTraced(k);
                //forwardGolden(k);
                //vn.clear();
                
		for(int i=0; i<Ci->gateSize(); ++i){
			
                        if((Ci->getGate(i)->getOutput(0)->val != Ci->getGate(i)->getOutput(0)->getVal())||(!(Ci->getGate(i)->getOutput(0)->isKnown()))){
                                Ci->getGate(i)->getOutput(0)->sw +=1;
                                tsw2++;
                        }
			
			Ci->getGate(i)->getOutput(0)->val = Ci->getGate(i)->getOutput(0)->getVal();
		}
		
		for(int i=0; i<Ci->flipflopSize(); ++i){
			
                        if((Ci->getFlipflop(i)->getOutput(0)->val != Ci->getFlipflop(i)->getOutput(0)->getVal())||(!(Ci->getFlipflop(i)->getOutput(0)->isKnown()))){
                                Ci->getFlipflop(i)->getOutput(0)->sw +=1;
                                tsw2++;
                        }
			
			Ci->getFlipflop(i)->getOutput(0)->val = Ci->getFlipflop(i)->getOutput(0)->getVal();
		}
		
		err1 += (float(abs(tsw1-tsw2)))/max(tsw1,tsw2);
		for(int i=0; i<Ci->flipflopSize(); ++i){
                        if(Ci->getFlipflop(i)->getOutput(0)->getTraced() == true)
                                traced_id = i;
                                
			if(Ci->getFlipflop(i)->getOutput(0)->isKnown()){

				if(Ci->getFlipflop(i)->getOutput(0)->getVal())
					Ci->getFlipflop(i)->getOutput(0)->setFlag1(1);
				else
					Ci->getFlipflop(i)->getOutput(0)->setFlag0(1);
			
                                bool test=true;
				for(unsigned j=0; j<vn.size(); ++j)
					if(vn[j] == i){
						test = false;
						break;
					}
				if(test && (Ci->getFlipflop(i)->getOutput(0)->getTraced() == false))
					vn.push_back(i);	
			}
		}
                
                total_vn_cnt += vn.size();
        }
        
        sort(vn.begin(),vn.end(),less<int>());
        
        ofstream out;
        out.open(filename,ofstream::app);
        //out<< traced_id <<endl;
        //out<< traced_id << "\t"<<Ci->getFlipflop(traced_id)->getOutput(0)->getName()<< endl;
        for(unsigned j=0; j<vn.size(); ++j)
                //out<< vn[j] <<"\t"<<Ci->getFlipflop(vn[j])->getOutput(0)->getName()<<"\t";
                out<< vn[j] <<"\t";
        out<<endl;
        out.close();

	return (double)total_vn_cnt / (double)MC_NUM;
}

void Simulate::hueristicSelect(const char* filename, const int trace_size){
        
        int i,j,length;
        char *s;
        const int MAX_LINE_LENGTH = 65536;
        char line_buffer[MAX_LINE_LENGTH];
        
        ifstream infile(filename);
        map<int, set<int> > mymap;
        map<int, set<int> >::iterator it_map;
        map<int, set<int> >::iterator it_map1;
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        
        for(i = 0; ;i++)
        {
                if(!infile.getline(line_buffer, MAX_LINE_LENGTH))
                        break;
                else{
                        s = strtok(line_buffer,"\t ");
                        if(s == NULL)
                                continue;
                        else{
                                mymap[i].insert(atoi(s));
                                while((s = strtok(NULL,"\t ")) != NULL)
                                        mymap[i].insert(atoi(s));
                        }
                }
        }
        
        /*
        for(it_map = mymap.begin();it_map != mymap.end();it_map++)
        {
                cout<<(*it_map).first<<endl;
                for(it_set = (*it_map).second.begin();it_set != (*it_map).second.end();it_set++)
                        cout<<(*it_set)<<"\t";
                cout<<endl;
        }
        */
        cout<<"Should be less than or equal to the DFF size "<<mymap.size()<<endl;
        int pre;
        vector<int> selected_traces;
        vector<int>::iterator it_vec;
        
        i = 0;
        while(i != trace_size)
        {
                length = 0;
                for(it_map = mymap.begin();it_map != mymap.end();it_map++)
                {
                        if((*it_map).second.size() > length)
                        {
                                it_map1 = it_map;
                                length = (*it_map).second.size();
                        }
                }
                
                if(length == 0)
                        break;
                
                cout<<"Choosen flipflop is "<< (*it_map1).first <<endl;

                i++;
                selected_traces.push_back((*it_map1).first);
                for(it_map = mymap.begin(); it_map != mymap.end(); it_map++)
                {
                        if(it_map != it_map1)
                        {
                                for(it_set = (*it_map1).second.begin(); it_set != (*it_map1).second.end(); it_set++)
                                {
                                        it_set1 = (*it_map).second.find(*it_set);
                                        if(it_set1 != (*it_map).second.end())
                                                (*it_map).second.erase(it_set1);
                                }
                        }
                }
                
                mymap.erase(it_map1);
        }
        
        cout<<"seleted signals are...."<<endl;
        cout<<"seleted signals size is "<< selected_traces.size()<<endl;
        clearTraced();
        for(int i=0; i<Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false);

        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true);
                tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
        }
        
        cout<<"Hueristic selection result is "<<computVN()<<endl;
}

bool Simulate::simHybrid1Trace(bool test)
{
        list<Signal*> sigList;
	bool cont=false;
        
        for(int i=0; i<Ci->flipflopSize(); ++i)
                if(Ci->getFlipflop(i)->getOutput(0)->getTraced())
                {
                        if(test == true)
                                Ci->getFlipflop(i)->getOutput(0)->setVal(One);
                        else
                                Ci->getFlipflop(i)->getOutput(0)->setVal(Zero);
                        
                        Ci->getFlipflop(i)->setInput();
                        sigList.push_back(Ci->getFlipflop(i)->getInput(1));
			sigList.push_back(Ci->getFlipflop(i)->getOutput(0));
                }
        
        Signal *s;
	while (!sigList.empty())
        {
                s = sigList.front();
                sigList.erase(sigList.begin());
                
                if(s->stored == 1)
                        continue;
#ifdef DEBUG_SIMULATE
                cout<<"Current signals in list are"<<endl;
                for(list<Signal*>::iterator it=sigList.begin(); it!=sigList.end(); ++it)
                        cout<<(*it)->getName()<<"\t";
                cout<<endl;
                
                cout<<"signal under simulation "<< s->getName() << " value " << s->getVal()<< endl;
                cin.get();
#endif                
                s->stored = 1;
                
                if(s->outputSize()!=0){
                        if(s->getOutput(0)->signature()!=INPUT){
                                for(int i=0; i<s->outputSize(); ++i){
                                        
                                        if(s->getOutput(i)->isActive()){
                                                cont=true;
                                                
                                                for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b') 
                                                                sigList.push_back(s->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                        else{
                                
                                for(int i=1; i<s->outputSize(); ++i){
                                        if(s->getOutput(i)->isActive()){
                                                
                                                cont=true;	
                                                for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' )
                                                                sigList.push_back(s->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                }
                if(s->inputSize()!=0){
                        if(s->getInput(0)->signature()!=OUTPUT){
                                for(int i=0; i<s->inputSize(); ++i){
                                        
                                        if(s->getInput(i)->isBackwardActive()){
                                                
                                                s->getInput(i)->setBackwardVisited(true);
                                                cont=true;
                                                
                                                for(int j=0; j<s->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && s->getInput(i)->getInput(j)->getName().c_str()[0] != 'b')
                                                                sigList.push_back(s->getInput(i)->getInput(j));
                                                }
                                        }
                                }
                        }
                        else
                        {
                                for(int i = 1; i < s->inputSize(); ++i){
                                        
                                        if(s->getInput(i)->isBackwardActive()){
                                                
                                                s->getInput(i)->setBackwardVisited(true);
                                                cont=true;
                                                        
                                                for(int j=0; j<s->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && s->getInput(i)->getInput(j)->getName().c_str()[0] != 'b') 
                                                           sigList.push_back(s->getInput(i)->getInput(j));
                                                }
                                        }
                                }
                        }
                }
        }
        
        return cont;
}

void Simulate::hueristicSelect2(const int trace_size, const char* filename){
        
        int i,j,k,flag;
        double weight, temp_weight;
        vector<resMap*> Mymap;
        vector<resMap*>::iterator it_map;
        vector<resMap*>::iterator it_map1;
        
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        
        vector<int> selected_traces;
        vector<int>::iterator it_vec;
        for(i = 0; i < Ci->flipflopSize(); ++i)
        {
                flag = 0;
                resMap* MyresMap = new resMap;
                clearTraced();
                Ci->getFlipflop(i)->getOutput(0)->setTraced(true);
                addTraced(Ci->getFlipflop(i)->getOutput(0));

                initSimulateHybrid();
                simHybrid1Trace(true);
                
                MyresMap->DFF_id = i;
                MyresMap->P0 = Ci->getFlipflop(i)->getOutput(0)->getP0();
                MyresMap->P1 = Ci->getFlipflop(i)->getOutput(0)->getP1();
                
                if(MyresMap->P0 == 0.0 && MyresMap->P1 == 0.0)
                {
                        cout<<"no Way!"<<endl;
                        cout<<"the signal name is "<<Ci->getFlipflop(i)->getOutput(0)->getName()<<endl;
                }
                        
                for(k =0; k<Ci->flipflopSize(); ++k)
			if(Ci->getFlipflop(k)->getOutput(0)->isKnown())
				if(Ci->getFlipflop(k)->getOutput(0)->getTraced() == false)
                                {
                                        flag = 1;
                                        MyresMap->R1.insert(k);
                                }
                
                initSimulateHybrid();
                simHybrid1Trace(false);
                
                for(k =0; k<Ci->flipflopSize(); ++k)
			if(Ci->getFlipflop(k)->getOutput(0)->isKnown())
				if(Ci->getFlipflop(k)->getOutput(0)->getTraced() == false)
                                {
                                        flag = 1;
                                        MyresMap->R0.insert(k);
                                }
                
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false);
                
                if(flag == 1)
                        Mymap.push_back(MyresMap);
        }
        
        if(filename == NULL)
        {
                for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                {
                        cout<<"DFF # "<<(*it_map)->DFF_id<<"\t"<<(*it_map)->P0<<"\t"<<(*it_map)->P1<<endl;
                        cout<<"restored DFF from 0"<<endl;
                        for(it_set = (*it_map)->R0.begin(); it_set != (*it_map)->R0.end(); it_set++)
                                cout<<*it_set<<"\t";
                        cout<<endl;
                
                        cout<<"restored DFF from 1"<<endl;
                        for(it_set = (*it_map)->R1.begin(); it_set != (*it_map)->R1.end(); it_set++)
                                cout<<*it_set<<"\t";
                        cout<<endl;
                }
        }
        else
        {
                ofstream out(filename);
                for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                {
                        out<<"DFF # "<<(*it_map)->DFF_id<<"\t"<<(*it_map)->P0<<"\t"<<(*it_map)->P1<<endl;
                        out<<"restored DFF from 0"<<endl;
                        for(it_set = (*it_map)->R0.begin(); it_set != (*it_map)->R0.end(); it_set++)
                                out<<*it_set<<"\t";
                        out<<endl;
                
                        out<<"restored DFF from 1"<<endl;
                        for(it_set = (*it_map)->R1.begin(); it_set != (*it_map)->R1.end(); it_set++)
                                out<<*it_set<<"\t";
                        out<<endl;
                }
        }
        
        i = 0;
        while(i != trace_size)
        {
                weight = 0.0;
                for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                {
                        temp_weight = (*it_map)->R0.size() * (*it_map)->P0 + 
                                (*it_map)->R1.size() * (*it_map)->P1;
                        
                        if(temp_weight > weight)
                        {
                                it_map1 = it_map;
                                weight = temp_weight;
                        }
                }
                
                if(weight == 0.0)
                        break;
              
                cout<<"Choosen flipflop is "<< (*it_map1)->DFF_id <<endl;

                i++;
                selected_traces.push_back((*it_map1)->DFF_id);
                for(it_map = Mymap.begin(); it_map != Mymap.end(); it_map++)
                {
                        if(it_map != it_map1)
                        {
                                for(it_set = (*it_map1)->R0.begin(); it_set != (*it_map1)->R0.end(); it_set++)
                                {
                                        it_set1 = (*it_map)->R0.find(*it_set);
                                        if(it_set1 != (*it_map)->R0.end() && (*it_map)->P0 <= (*it_map1)->P0)
                                                (*it_map)->R0.erase(it_set1);
                                        
                                        it_set1 = (*it_map)->R1.find(*it_set);
                                        if(it_set1 != (*it_map)->R1.end() && (*it_map)->P1 <= (*it_map1)->P0)
                                                (*it_map)->R1.erase(it_set1);
                              
                                }
                                
                                for(it_set = (*it_map1)->R1.begin(); it_set != (*it_map1)->R1.end(); it_set++)
                                {
                                        it_set1 = (*it_map)->R1.find(*it_set);
                                        if(it_set1 != (*it_map)->R1.end() && (*it_map)->P1 <= (*it_map1)->P1)
                                                (*it_map)->R1.erase(it_set1);
                                
                                        it_set1 = (*it_map)->R0.find(*it_set);
                                        if(it_set1 != (*it_map)->R0.end() && (*it_map)->P0 <= (*it_map1)->P1)
                                                (*it_map)->R0.erase(it_set1);
                                }
                        }
                }

                Mymap.erase(it_map1);
        }
        
        cout<<"seleted signals are...."<<endl;
        clearTraced();
        for(int i=0; i<Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false);

        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<endl;
                Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true);
                tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
        }
        
        cout<<"Hueristic selection result is "<<computVN()<<endl;        
}


double Simulate::simSelect(const int trace_size){
        
        Conf* c1;
        Confset* C2 = new Confset();
        Confset* C1 = new Confset();

        for(int i=0; i<Ci->flipflopSize(); ++i)
        {
                c1 = new Conf();
                clearTraced();
                addTraced(Ci->getFlipflop(i)->getOutput(0));
                c1->tracedSigs.push_back(Ci->getFlipflop(i)->getOutput(0));
                c1->tracedSigs[0]->setTraced(true);
                c1->TV = computVN();
                c1->TVNC = c1->TV;
                C1->confs.push_back(c1);
                c1->tracedSigs[0]->setTraced(false);
        }
        
        C1->min();
        C1->reduce();
        
        for(int k = 1; k < trace_size; ++k){
                
		delete C2;
		C2 = new Confset();
		
		for(int k1=0; k1<C1->confs.size(); ++k1){

			tracedSigs.clear();	
			for(int k2=0; k2<C1->confs[k1]->tracedSigs.size(); ++k2){
                                C1->confs[k1]->tracedSigs[k2]->setTraced(true);
				tracedSigs.push_back(C1->confs[k1]->tracedSigs[k2]);
			}
			
			for(int i=0; i<Ci->flipflopSize(); ++i){
                                if( (!Ci->getFlipflop(i)->getOutput(0)->getTraced())){//not traced
					
                                        Ci->getFlipflop(i)->getOutput(0)->setTraced(true);
                                        addTraced(Ci->getFlipflop(i)->getOutput(0));
                                        
                                        c1 = new Conf();
                                        for(int j=0; j<tracedSigs.size(); ++j)
						c1->tracedSigs.push_back(tracedSigs[j]);
                                        c1->TV = computVN();
                                        c1->TVNC = c1->TV;
                                        C2->confs.push_back(c1);
                                        
                                        Ci->getFlipflop(i)->getOutput(0)->setTraced(false);
                                        tracedSigs.pop_back();
				}
			}	
		}

		C2->min();
		C2->reduce();
		swap(C1,C2);
        }
        
        C1->min();
        C1->reduce();
        int mc = C1->maxTV();
        tracedSigs.clear();
        
        for(int k2=0; k2<C1->confs[mc]->tracedSigs.size(); ++k2){
                tracedSigs.push_back(C1->confs[mc]->tracedSigs[k2]);
                C1->confs[mc]->tracedSigs[k2]->setTraced(true);
        }
        
        printTraced();
        return C1->confs[mc]->TV;
}

